package pointerybxb

import (
	"fmt"
)

// Go语言中，指针操作非常简单，只需要记住三个符号：
//  1.&变量: 取变量的地址
//	2.*变量: 根据地址取变量值、*数据类型表示指针类型。注意：*只能针对内存地址类型的数据。
//  3.*int: 表示int类型的指针，是一种数据类型

func TestPorterDefault() {
	// 变量abc是指针类型
	var abc = new(int) // new函数是初始化变量，返回值是这个变量的指针地址。
	// *abc = 12
	fmt.Println(*abc) // 当变量abc是指针时，"*abc"是获取指针指向的值。
}

func TestPointer() {
	var a = 10
	fmt.Printf("变量a的内存地址是：%v\n", &a)   // 变量a的内存地址是：0xc00000a0e8
	fmt.Printf("变量a的内存地址的类型：%T\n", &a) // 变量a的内存地址的类型：*int

	fmt.Printf("变量a的内存地址是：%v\n", *&a) // 变量a的内存地址是：0xc00000a0e8
	fmt.Printf("变量a的内存地址是：%d\n", &a)  // 变量a的内存地址是：824633762024

	fmt.Printf("变量a的值是：%d\n", *&a)  // 变量a的值是：10
	fmt.Printf("变量a的类型是：%T\n", *&a) // 变量a的类型是：int

	fmt.Println("--------------------")
	var b = &a
	// &b是变量b本身的内存地址
	// b是变量a的内粗地址
	// *b代表的是变量a的值
	fmt.Println(&b, b, *b)
}

func TestPointer1() {
	var a = 10
	var b = &a
	var c = *&a    // 等价于:*b   区别与:*int   前者是获取变量的值，后者是指针类型(是一种数据类型)
	fmt.Println(a) // 10是变量a的值
	fmt.Println(b) // 0xc00000a0e8是变量a的内存值
	fmt.Println(c) // 10是变量a的值。*&a是通过变量a的内存地址获取变量a的值
}

func TestPointer2() {
	var abc *int
	fmt.Printf("%T, %v\n", abc, abc)   // *int
	fmt.Printf("%T, %v\n", &abc, &abc) // **int
}

func TestPointer3() {
	var abc = 100
	p := &abc // p是一级指针，类型为*int，存储abc的地址
	pp := &p  // pp是二级指针，类型为**int，存储p的指针
	fmt.Printf("abc的值:%d\n", abc)
	fmt.Printf("p存储的地址(就是值):%p(指向num)\n", p)
	fmt.Printf("pp存储的地址(就是值):%p(指向p)\n", pp)
	fmt.Printf("p本身的地址:%p(与pp存储的地址相同)\n", &p) //  &p:获取变量p的地址。
	// %p: 打印内存地址
}

// 定义结构体
type Student struct {
	Name string
	Age  int
}

func TestStuStruct() {
	var stu *Student
	stu = new(Student) // 分配内存空间,stu是指针类型:*Student
	stu.Name = "hy.bai"
	stu.Age = 18
	fmt.Println(stu) // 打印结果:&{hy.bai 18}
}
